home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Frameworks / Sprocket Framework DR2 / Sprocket Framework / DialogWindow.cp < prev    next >
Text File  |  1996-06-15  |  8KB  |  320 lines

  1. /*
  2.  
  3.     File:        DialogWindow.cp
  4.     Project:    Sprocket Framework 1.1 (DR2), released 6/15/96
  5.     Contains:    Sub-class of TWindow to handle dialogs
  6.     To Do:        ?
  7.  
  8.     Sprocket Major Contributors:
  9.     ----------------------------
  10.     Dave Falkenburg, producer of Sprocket 1.0
  11.     Bill Hayden,     producer of Sprocket 1.1
  12.     Steve Sisak,     producer of the upcoming Sprocket 2.0
  13.     
  14.     Pete Alexander        Steve Falkenburg    Randy Thelen
  15.     Eric Berdahl        Nitin Ganatra        Chris K. Thomas
  16.     Marshall Clow        Dave Hershey        Leonard Rosenthal
  17.     Tim Craycroft        Dave Mark            Dean Yu
  18.     David denBoer        Gary Powell
  19.     Cameron Esfahani    Jon Summers            Apple Computer, Inc.
  20.         
  21.     Comments, Additions, or Corrections:
  22.     ------------------------------------
  23.     Bill Hayden, Nikol Software <nikol@codewell.com>
  24.  
  25. */
  26.  
  27. #include "Sprocket.h"
  28. #include "UDialog.h"
  29.  
  30. #include "DialogWindow.h"
  31. #include <Traps.h>
  32.  
  33.  
  34.  
  35. TDialogWindow::TDialogWindow(DialogTemplateID dialogTemplateID)
  36. {
  37.     fTemplateID = dialogTemplateID;
  38.     fIsDialogWindow = true;
  39. }
  40.  
  41.  
  42.  
  43. WindowRef TDialogWindow::MakeNewWindow(WindowRef behindWindow)
  44. {
  45.     return GetDialogWindow ( GetNewDialog(fTemplateID, nil, (WindowRef) behindWindow));
  46. }
  47.  
  48.  
  49.  
  50. Boolean TDialogWindow::Close(void)
  51. {
  52.     Boolean retVal = TWindow::Close ();
  53.  
  54.     //    We have to do this in case we are the last window open
  55.     //    We don't want to leave the menu items enabled
  56.     
  57.     if ( retVal )
  58.         {
  59.         gMenuBar->EnableCommand ( cCut,            false );
  60.         gMenuBar->EnableCommand ( cCopy,        false );
  61.         gMenuBar->EnableCommand ( cPaste,        false );
  62.         gMenuBar->EnableCommand ( cClear,        false );
  63.         gMenuBar->EnableCommand ( cSelectAll,    false );
  64.                 
  65.         OSErr err = gMenuBar->HiliteMenusForModalDialog(true);
  66.         if (err)
  67.             ErrorReporter(err, __FILE__, __LINE__);            
  68.         }
  69.  
  70.     return retVal;
  71. }
  72.  
  73. ////////////////////////////////////////////////////////////////////////////////////
  74. //
  75. //    EventFilter strategy for Dialog Window
  76. //
  77. //    Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
  78. //    and DialogSelect, only do these things when a Modeless Dialog is the frontmost
  79. //    window. (e.g., it’s event filter is active)
  80. //
  81. //    NOTE: We always pass events through, except when an item has been hit.
  82. //
  83. //    You may be thinking that it is easier to just rewrite the Dialog Manager in
  84. //    this program. You’re probably right.
  85.  
  86. pascal    WindowRef    FrontWindowPatchForDialogs();
  87.  
  88.  
  89. pascal    WindowRef
  90. FrontWindowPatchForDialogs()
  91.     {
  92.     return FrontNonFloatingWindow();
  93.     }
  94.  
  95. #define    uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowRef))))
  96.  
  97. UniversalProcPtr FrontWindowPatchUPP
  98. = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
  99.  
  100.  
  101. Boolean TDialogWindow::EventFilter(EventRecord *theEvent)
  102. {
  103.     GrafPtr                oldPort;
  104.     UniversalProcPtr    oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
  105.     DialogRef            aDialog;
  106.     Boolean                eventHasBeenGobbled = false;
  107.     short                aDialogItem = 0;
  108.     short                oldWindowKind;
  109.     
  110.     //    Don’t snarf keypresses meant for menus
  111.     if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
  112.         return false;
  113.  
  114.     GetPort(&oldPort);
  115.     SetGrafPortOfDialog ( GetDialogRef ());
  116.     
  117.     //    Patch in our version of FrontWindow so that IsDialogEvent will do the right
  118.     //    thing. DialogManager should check both frontmost floating and frontmost
  119.     //    non-floating windows, however we don’t support floating dialogs.
  120.     
  121.     SetToolboxTrapAddress(FrontWindowPatchUPP, _FrontWindow);
  122.  
  123.     //    Jam the windowKind of our dialog window back to dialogKind so that the
  124.     //    Dialog Manager can recognize our window as a dialog window.
  125.     
  126.     oldWindowKind = GetWindowKind(fWindow);
  127.     SetWindowKind(fWindow, dialogKind);
  128.     
  129.     
  130.     if (IsDialogEvent(theEvent))
  131.         {
  132.         //    It’s definitely a dialog event, so let the Dialog Manager figure things out.
  133.         //
  134.         //    We first let StdFilterProc have a crack at it so that the default
  135.         //    and cancel buttons are properly processed (as well as automagic text
  136.         //    cursor tracking).
  137.         
  138.         //    If StdFilterProc didn’t find anything to do, go ahead and call
  139.         //    DialogSelect to figure out if the user did anything important.
  140.  
  141.         //    Isn’t this alot easier than what Inside Mac says to do?
  142.  
  143.         eventHasBeenGobbled = StdFilterProc( GetDialogRef (),theEvent,&aDialogItem);
  144.  
  145.         //    Give the window a chance to pre-process the event
  146.         //    This is useful for people who want to implement read-only text items (for example)
  147.     
  148.         if (eventHasBeenGobbled == false)
  149.             eventHasBeenGobbled = this->FilterDialogEvent ( theEvent, &aDialogItem );
  150.             
  151.         //    Let the dialog manager deal with the event
  152.         
  153.         if (eventHasBeenGobbled == false)
  154.             eventHasBeenGobbled = DialogSelect(theEvent,&aDialog,&aDialogItem);
  155.         }
  156.  
  157.     //    Restore the windowKind
  158.     
  159.     SetWindowKind(fWindow, oldWindowKind);
  160.  
  161.     //    Put FrontWindow back the way it really belongs
  162.     
  163.     SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow, _FrontWindow);
  164.  
  165.     if (eventHasBeenGobbled)
  166.         {
  167.         this->ItemHit(aDialogItem);    //    Call user’s method to deal with a hit
  168.         eventHasBeenGobbled = true;
  169.         }
  170.         
  171.     SetPort(oldPort);
  172.     
  173.     return eventHasBeenGobbled;
  174. }
  175.  
  176.  
  177.  
  178. /*****************************************************************************/
  179.  
  180.  
  181.  
  182. Boolean TDialogWindow::FilterDialogEvent(EventRecord */*theEvent*/, short *itemHit )
  183. {
  184.     *itemHit = 0;
  185.     return false;    // Event not handled
  186. }
  187.  
  188.  
  189.  
  190. /*****************************************************************************/
  191.  
  192.  
  193.  
  194. void TDialogWindow::Activate(Boolean activating)
  195. {
  196.     EventRecord            fakeEvent;
  197.  
  198.     /*    (De)activates are NOT automagically handled because our floating
  199.      *    windows prevent real activate events from ever being generated
  200.      *    for any non-floaters windows.
  201.      *
  202.      *    Our strategy is to fool the dialog manager into thinking that
  203.      *    things are still fine by passing it a fake (de)activate event.
  204.      *
  205.      *    Luckily, we don’t have to patch FrontWindow to make DialogSelect
  206.      *    work for activate and update events.
  207.      */
  208.         
  209.     OSEventAvail(0, &fakeEvent);        //    Get an intialized, but otherwise empty event record
  210.     
  211.     fakeEvent.what = activateEvt;
  212.     fakeEvent.message = (unsigned long) GetDialogRef ();
  213.     if (activating)
  214.         fakeEvent.modifiers |= activeFlag;
  215.     else
  216.         fakeEvent.modifiers &= ~activeFlag;
  217.  
  218.     //    Pass event on to DialogSelect
  219.     
  220.     DialogRef    aDialog;
  221.     short        aDialogItem;
  222.     
  223.     (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
  224. }
  225.     
  226.  
  227.  
  228. /*****************************************************************************/
  229.  
  230.  
  231.  
  232. void TDialogWindow::Draw(void)
  233. {
  234.     //    Automagically handled by Dialog Manager when we are
  235.     //    the frontmost window, but not at other times because
  236.     //    we only set the windowKind to dialogKind inside our
  237.     //    EventFilter (which is only active when we are frontmost).
  238.     RgnHandle    update = NewRgn ();
  239.     GetWindowUpdateRgn ( fWindow, update );
  240.     UpdateDialog ( GetDialogRef (), update );
  241.     DisposeRgn ( update );
  242. }
  243.     
  244.  
  245.     
  246. /*****************************************************************************/
  247.  
  248.  
  249.  
  250. void TDialogWindow::Click(EventRecord * /* anEvent */)
  251. {
  252.     /*    The only time this method is called is to handle a click
  253.      *    when the dialog window isn’t frontmost. All other times,
  254.      *    DialogSelect will do everything for us.
  255.      *
  256.      *    If our dialog contains useritems with the ability to
  257.      *    be the source of a drag we’d need to start drag tracking
  258.      *    in here.
  259.      */
  260.      
  261.     this->Select();
  262. }
  263.  
  264.  
  265.  
  266. /*****************************************************************************/
  267.  
  268.  
  269.  
  270. void TDialogWindow::AdjustMenusBeforeMenuSelection(void)
  271. {
  272.     TEHandle    teh = GetDialogTextEdit ( GetDialogRef() );
  273.     Boolean        validSelection = teh != NULL && ( (*teh)->selStart != (*teh)->selEnd );
  274.     
  275.     gMenuBar->EnableCommand ( cCut,   validSelection );
  276.     gMenuBar->EnableCommand ( cCopy,  validSelection );
  277.     gMenuBar->EnableCommand ( cPaste, true );    // we really should check the scrap
  278.     gMenuBar->EnableCommand ( cClear, validSelection );
  279.  
  280.     gMenuBar->EnableCommand ( cSelectAll, teh != NULL );
  281. }
  282.  
  283.  
  284.  
  285. /*****************************************************************************/
  286.  
  287.  
  288.  
  289. Boolean TDialogWindow::DoCommand(CommandID command)
  290. {
  291.     DialogRef    theDialog =  GetDialogRef ();
  292.  
  293.     switch (command)
  294.         {
  295.         case    cCut:
  296.             DialogCut(theDialog);
  297.             return true;
  298.             
  299.         case    cCopy:
  300.             DialogCopy(theDialog); 
  301.             return true;
  302.             
  303.         case    cPaste:
  304.             DialogPaste(theDialog); 
  305.             return true;
  306.             
  307.         case    cClear:
  308.             DialogDelete(theDialog); 
  309.             return true;
  310.  
  311.         case    cSelectAll:
  312.             SelectDialogItemText ( theDialog, GetDialogKeyboardFocusItem ( theDialog ), 0, 32767 );
  313.             return true;
  314.         }
  315.  
  316.     //    If we don't handle it, then let the super-class handle it
  317.     
  318.     return TWindow::DoCommand ( command );
  319. }
  320.